import logging
from typing import Any, List, Dict, Optional, Union # Added Union for type hint
import asyncio # For TimeoutError

from core import logic_executor
from api_interfaces.internal_api_logic import InternalApiLogic

logger = logging.getLogger(__name__)

class PywebviewOuterApi:
    """
    作为 pywebview 同步 API 调用的入口点，并将这些调用桥接到 asyncio 逻辑循环。
    此类中的方法将具有与当前 api_bridge/js_api.py 中相同的同步函数签名。
    """
    def __init__(self):
        self._internal_api: Optional[InternalApiLogic] = None
        # 延迟获取 internal_api_logic 实例，因为它在 logic_executor 启动后才可用

    def _get_internal_api(self) -> InternalApiLogic:
        """
        获取 InternalApiLogic 实例。
        如果 logic_executor 尚未完全初始化 internal_api_logic，则可能会失败。
        """
        if self._internal_api is None:
            internal_api_instance = logic_executor.get_core_service('internal_api_logic')
            if internal_api_instance is None:
                logger.error("InternalApiLogic service not available from logic_executor.")
                raise RuntimeError("InternalApiLogic service not initialized.")
            self._internal_api = internal_api_instance
        return self._internal_api

    # 以下方法是根据旧的 js_api.py 的常见 API 模式创建的占位符
    # 它们将在 internal_api_logic.py 创建和定义其异步方法后被正确实现

    def handle_human_message_submission(self, message_text: str, tags: List[str]) -> Dict[str, Any]:
        """
        处理用户通过UI提交的消息。
        """
        logger.debug(f"PywebviewOuterApi: Received human message: {message_text}, tags: {tags}")
        try:
            internal_api = self._get_internal_api()
            coro = internal_api.handle_human_message_submission_async(message_text, tags)
            future = logic_executor.submit_to_logic_loop(coro)
            return future.result(timeout=30) # 30s timeout for message processing
        except asyncio.TimeoutError:
            logger.error("Timeout in handle_human_message_submission.")
            return {"success": False, "error": "Request timed out."}
        except Exception as e:
            logger.error(f"Error in handle_human_message_submission: {e}", exc_info=True)
            return {"success": False, "error": str(e)}

    def get_initial_chatroom_data(self) -> Dict[str, Any]:
        """
        获取初始聊天室数据。
        """
        logger.debug("PywebviewOuterApi: Request to get initial chatroom data.")
        try:
            internal_api = self._get_internal_api()
            coro = internal_api.get_initial_chatroom_data_async()
            future = logic_executor.submit_to_logic_loop(coro)
            return future.result(timeout=20) # 20s timeout
        except asyncio.TimeoutError:
            logger.error("Timeout in get_initial_chatroom_data.")
            return {"error": "Request timed out."} # Match typical error structure
        except Exception as e:
            logger.error(f"Error in get_initial_chatroom_data: {e}", exc_info=True)
            return {"error": str(e)} # Match typical error structure

    def get_all_chat_messages(self) -> List[Dict[str, Any]]: # Kept for compatibility if UI calls it
        """
        获取所有聊天消息 (通常通过 get_initial_chatroom_data 获取).
        """
        logger.debug("PywebviewOuterApi: Request to get all chat messages (delegating to initial data).")
        try:
            data = self.get_initial_chatroom_data()
            if "error" in data: # Propagate error if initial data call failed
                 return [{"error": data["error"]}]
            return data.get("chat_history", [{"error": "Chat history not found in initial data."}])
        except Exception as e: # Catch any other unexpected error
            logger.error(f"Error in get_all_chat_messages wrapper: {e}", exc_info=True)
            return [{"error": str(e)}]


    def get_all_participants(self) -> List[Dict[str, Any]]:
        """
        获取所有参与者信息。
        """
        logger.debug("PywebviewOuterApi: Request to get all participants.")
        try:
            internal_api = self._get_internal_api()
            coro = internal_api.get_all_participants_async()
            future = logic_executor.submit_to_logic_loop(coro)
            return future.result(timeout=10)
        except asyncio.TimeoutError:
            logger.error(f"Timeout in get_all_participants.")
            return [{"error": "Request timed out."}]
        except Exception as e:
            logger.error(f"Error in get_all_participants: {e}", exc_info=True)
            return [{"error": str(e)}]

    def get_agent_details(self, agent_id: str) -> Optional[Dict[str, Any]]:
        """
        获取特定代理的详细信息。
        """
        logger.debug(f"PywebviewOuterApi: Request to get agent details for agent_id: {agent_id}")
        try:
            internal_api = self._get_internal_api()
            coro = internal_api.get_agent_details_async(agent_id)
            future = logic_executor.submit_to_logic_loop(coro)
            # The async method might return None or raise an error.
            # future.result() will propagate the None or the error.
            return future.result(timeout=10)
        except asyncio.TimeoutError:
            logger.error(f"Timeout in get_agent_details for agent {agent_id}.")
            # Return type is Optional[Dict], so None is a valid error indicator here, or a dict with error
            return {"error": f"Request timed out for agent {agent_id}."}
        except Exception as e:
            logger.error(f"Error in get_agent_details for agent {agent_id}: {e}", exc_info=True)
            # Return type is Optional[Dict], so None is a valid error indicator here, or a dict with error
            return {"error": str(e)}

    def get_all_tags(self) -> List[Dict[str, Any]]:
        """
        获取所有标签。
        """
        logger.debug("PywebviewOuterApi: Request to get all tags.")
        try:
            internal_api = self._get_internal_api()
            coro = internal_api.get_all_tags_async()
            future = logic_executor.submit_to_logic_loop(coro)
            return future.result(timeout=10)
        except asyncio.TimeoutError:
            logger.error("Timeout in get_all_tags.")
            return [{"error": "Request timed out."}]
        except Exception as e:
            logger.error(f"Error in get_all_tags: {e}", exc_info=True)
            return [{"error": str(e)}]

    def add_whiteboard_item(self, file_path: str) -> Dict[str, Any]:
        logger.debug(f"PywebviewOuterApi: Request to add whiteboard item: {file_path}")
        try:
            internal_api = self._get_internal_api()
            coro = internal_api.add_whiteboard_item_async(file_path)
            future = logic_executor.submit_to_logic_loop(coro)
            return future.result(timeout=15)
        except asyncio.TimeoutError:
            logger.error(f"Timeout in add_whiteboard_item for {file_path}.")
            return {"success": False, "error": "Request timed out.", "whiteboard_items": []}
        except Exception as e:
            logger.error(f"Error in add_whiteboard_item: {e}", exc_info=True)
            # Attempt to get current items on error, consistent with old API
            current_items = []
            try:
                current_items_data = self.get_initial_chatroom_data()
                if "whiteboard_items" in current_items_data and isinstance(current_items_data["whiteboard_items"], list):
                    current_items = current_items_data["whiteboard_items"]
            except Exception as e_items:
                logger.error(f"Could not fetch current whiteboard items on error: {e_items}")
            return {"success": False, "error": str(e), "whiteboard_items": current_items}


    def remove_whiteboard_item(self, reference_id: str) -> Dict[str, Any]:
        logger.debug(f"PywebviewOuterApi: Request to remove whiteboard item: {reference_id}")
        try:
            internal_api = self._get_internal_api()
            coro = internal_api.remove_whiteboard_item_async(reference_id)
            future = logic_executor.submit_to_logic_loop(coro)
            return future.result(timeout=15)
        except asyncio.TimeoutError:
            logger.error(f"Timeout in remove_whiteboard_item for {reference_id}.")
            return {"success": False, "error": "Request timed out.", "whiteboard_items": []} # Provide empty list
        except Exception as e:
            logger.error(f"Error in remove_whiteboard_item: {e}", exc_info=True)
            current_items = []
            try:
                current_items_data = self.get_initial_chatroom_data()
                if "whiteboard_items" in current_items_data and isinstance(current_items_data["whiteboard_items"], list):
                    current_items = current_items_data["whiteboard_items"]
            except Exception as e_items:
                logger.error(f"Could not fetch current whiteboard items on error: {e_items}")
            return {"success": False, "error": str(e), "whiteboard_items": current_items}

    def get_agent_logs(self, agent_id: str, limit: int = 20) -> List[Dict[str, Any]]:
        logger.debug(f"PywebviewOuterApi: Request for agent logs: {agent_id}, limit: {limit}")
        try:
            internal_api = self._get_internal_api()
            coro = internal_api.get_agent_logs_async(agent_id, limit)
            future = logic_executor.submit_to_logic_loop(coro)
            return future.result(timeout=15)
        except asyncio.TimeoutError:
            logger.error(f"Timeout in get_agent_logs for {agent_id}.")
            return [{"error": "Request timed out."}]
        except Exception as e:
            logger.error(f"Error in get_agent_logs: {e}", exc_info=True)
            return [{"error": str(e)}]

    def get_active_tags_for_filter(self, limit: int = 10) -> List[Dict[str, Any]]:
        logger.debug(f"PywebviewOuterApi: Request for active tags, limit: {limit}")
        try:
            internal_api = self._get_internal_api()
            coro = internal_api.get_active_tags_for_filter_async(limit)
            future = logic_executor.submit_to_logic_loop(coro)
            return future.result(timeout=10)
        except asyncio.TimeoutError:
            logger.error("Timeout in get_active_tags_for_filter.")
            return [{"error": "Request timed out."}]
        except Exception as e:
            logger.error(f"Error in get_active_tags_for_filter: {e}", exc_info=True)
            return [{"error": str(e)}]

    def filter_chat_history_by_tags(self, tags: List[str], limit: int = 100) -> List[Dict[str, Any]]:
        logger.debug(f"PywebviewOuterApi: Request to filter chat history by tags: {tags}, limit: {limit}")
        try:
            internal_api = self._get_internal_api()
            coro = internal_api.filter_chat_history_by_tags_async(tags, limit)
            future = logic_executor.submit_to_logic_loop(coro)
            return future.result(timeout=15)
        except asyncio.TimeoutError:
            logger.error(f"Timeout in filter_chat_history_by_tags for tags {tags}.")
            return [{"error": "Request timed out."}]
        except Exception as e:
            logger.error(f"Error in filter_chat_history_by_tags: {e}", exc_info=True)
            return [{"error": str(e)}]
            
    # Special window control method
    def request_window_close(self):
        """
        请求关闭应用程序窗口。
        这个方法可能直接与 webview 实例交互，或者通过 main.py 中的机制。
        目前，它将尝试停止逻辑执行器。
        """
        logger.info("PywebviewOuterApi: Received request to close window.")
        try:
            # 这个方法可能需要更复杂的逻辑来通知 pywebview 关闭
            # 现在，我们只尝试停止后端逻辑
            logic_executor.stop_logic_executor()
            # 通常，关闭请求由 pywebview 的关闭回调处理，
            # 然后该回调会调用 logic_executor.stop_logic_executor()。
            # 此处直接调用可能用于某些特殊场景或测试。
            # pywebview.destroy_window() # 不能在这里直接调用，因为它没有 webview 实例的引用
            print("Window close requested. Logic executor stop initiated.")
            return {"status": "close_requested"}
        except Exception as e:
            logger.error(f"Error in request_window_close: {e}", exc_info=True)
            return {"status": "error", "message": str(e)}